package main;

import iterator.Iterator;

import java.util.NoSuchElementException;

import visitor.Visitor;
import wrapper.Comparable;

import container.AbstractContainer;
import container.ContainerEmptyException;
import container.Stack;
import enumeration.Enumeration;

public class StackAsLinkedList extends AbstractContainer implements Stack{
	protected LinkedList list;

	public StackAsLinkedList() {
		list = new LinkedList();
	}

	public void push(Object object) {
		list.prepend(object);
		++count;
	}

	public Object pop() {
		try {
			if (count == 0)
				throw new ContainerEmptyException("A pilha está vazia");
		} catch (ContainerEmptyException e) {
			e.printStackTrace();
		}
		Object result = list.getFirst();
		list.extract(result);
		--count;
		return result;
	}

	public Object getTop() {
		try {
			if (count == 0)
				throw new ContainerEmptyException("A pilha está vazia");
		} catch (ContainerEmptyException e) {
			e.printStackTrace();
		}
		return list.getFirst();
	}

	public void accept(Visitor visitor) {
		for (LinkedList.Element ptr = list.getHead(); ptr != null; ptr = ptr
				.getNext()) {
			visitor.visit(ptr.getDatum());
			if (visitor.isDone())
				return;
		}
	}

	public Enumeration getEnumeration() {
		return new Enumeration() {
			protected LinkedList.Element position = list.getHead();

			public boolean hasMoreElements() {
				return position != null;
			}

			public Object nextElement() {
				if (position == null)
					throw new NoSuchElementException(
							"Elemento não encontrado na lista");
				Object result = position.getDatum();
				position = position.getNext();
				return result;
			}
		};
	}

	public void purge() {
		list.purge();
		count = 0;
	}

	@Override
	protected int compareTo(Comparable arg) {
		// TODO Auto-generated method stub
		return 0;
	}

	public Iterator getIterator() {
		return new Iterator()
		{
			protected LinkedList.Element position;
			
			public void init()
			{
				position = list.getHead();
			}
			
			public boolean test()
			{
				return position != null;
			}
			
			public void inc()
			{
				position = position.getNext();
			}
			
			public Object current()
			{
				return position.getDatum();
			}
		};
	}

}
